package com.itheima.stock.service.impl;

import com.google.common.base.Strings;
import com.itheima.stock.common.CommonConfig;
import com.itheima.stock.mapper.SysUserMapper;
import com.itheima.stock.pojo.SysUser;
import com.itheima.stock.service.UserService;
import com.itheima.stock.utils.IdWorker;
import com.itheima.stock.vo.LoginReqVo;
import com.itheima.stock.vo.LoginRespVo;
import com.itheima.stock.vo.R;
import com.itheima.stock.vo.ResponseCode;
import org.apache.commons.lang3.RandomStringUtils;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    SysUserMapper userMapper;

    //使用先导依赖并配置
    @Autowired
    PasswordEncoder passwordEncoder;
    //导入生成唯一标识的对象
    @Autowired
    IdWorker idWorker;
    //注入Redis操作对象
    @Autowired
    RedisTemplate redisTemplate;

    @Override
    public R<List<SysUser>> findAllUser() {

        List<SysUser> allUser = userMapper.findAllUser();
        return R.ok(allUser);
    }

    //登录判断
    @Override
    public R<LoginRespVo> login(LoginReqVo loginReqVo) {
        /**
         * 1.判断用户名和密码是否存在
         *      补充：如果随机校验码或者sessionId:rkey必须存在，否则校验失败
         *      补充：先redis下的验证码校验 因为速度足够块
         * 2.根据用户名查询用户信息，并判断用户是否存在
         * 3.判断查询的db中的密码与前端传入的密码进行校验
         * 4.成功，封装并响应数据
         * 使用的工具类：
         *      Strings：google.common包，用于判断是否为空
         *      BeanUtils.copyProperties：Spring框架的工具类，用于自动封装实体类
         */
        if (loginReqVo == null || Strings.isNullOrEmpty(loginReqVo.getUsername()) || Strings.isNullOrEmpty(loginReqVo.getPassword()) || Strings.isNullOrEmpty(loginReqVo.getCode()) || Strings.isNullOrEmpty(loginReqVo.getRkey())) {
            return R.error(ResponseCode.DATA_ERROR.getMessage());
        }
        //从Redis获取验证码,不相等或为空则返回错误不存在
        String rCode = (String) redisTemplate.opsForValue().get(loginReqVo.getRkey());
        if (rCode==null||!rCode.equals(loginReqVo.getCode())) {
            return R.error(ResponseCode.DATA_ERROR.getMessage());
        }
        //从根据用户名查询数据库中的信息，没有就返回不存在
        SysUser userName = userMapper.findUserByUserName(loginReqVo.getUsername());
        if (userName == null) {
            return R.error(ResponseCode.SYSTEM_USERNAME_NOT_EXISTS.getMessage());
        }
        //密码进行编码匹配
        boolean flag = passwordEncoder.matches(loginReqVo.getPassword(), userName.getPassword());
        if (!flag) {
            return R.error(ResponseCode.SYSTEM_PASSWORD_ERROR.getMessage());
        }
        //没有问题就响应成功
        LoginRespVo loginRespVo = new LoginRespVo();
//        loginRespVo.setId(userName.getId());
//        loginRespVo.setUsername(userName.getUsername());
        //使用工具类进行封装，省略上面步骤
        //第一个参数为封装的参数，第二个为封装的目标
        BeanUtils.copyProperties(userName, loginRespVo);
        return R.ok(loginRespVo);
    }


    //生成验证码
    @Override
    public R<Map> generateCaptcha() {
        /**
         * 1.生成4位数字验证码
         * 2.获取全局唯一id
         * 3.验证码存入redis中，并设置有效期1分钟
         * 4.封装数据,返回前端
         * 使用的工具类：
         * randomNumeric
         *      属于apache.commons
         *      用于生成各种随机码
         *      randomNumeric生成数据数字。参数为位数
         *  idWorker
         *      使用雪花算法生成的唯一标识id,模拟JSessionId
         *      返回的是long类型，需要转换
         */
        String s = RandomStringUtils.randomNumeric(4);
        long nextId = idWorker.nextId();
        String rkey = Long.toString(nextId);
        //验证码存入redis中，并设置有效期1分钟
        redisTemplate.opsForValue().set(rkey, s, 1, TimeUnit.MINUTES);
        HashMap<String, String> map = new HashMap<>();
        map.put("rkey", rkey);
        map.put("code", s);
        return R.ok(map);
    }
}
